package com.emex.app.stuff.utils;

import ar.com.fdvs.dj.core.DynamicJasperHelper;
import ar.com.fdvs.dj.core.layout.ClassicLayoutManager;
import ar.com.fdvs.dj.domain.DynamicReport;
import ar.com.fdvs.dj.domain.Style;
import ar.com.fdvs.dj.domain.builders.ColumnBuilder;
import ar.com.fdvs.dj.domain.builders.FastReportBuilder;
import ar.com.fdvs.dj.domain.constants.Border;
import ar.com.fdvs.dj.domain.constants.Font;
import ar.com.fdvs.dj.domain.constants.HorizontalAlign;
import ar.com.fdvs.dj.domain.constants.Page;
import ar.com.fdvs.dj.domain.constants.Stretching;
import ar.com.fdvs.dj.domain.constants.VerticalAlign;
import ar.com.fdvs.dj.domain.entities.columns.AbstractColumn;
import java.awt.Color;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import javax.swing.JDialog;
import javax.swing.JTable;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableModel;
import net.sf.jasperreports.engine.JRDataSource;
import net.sf.jasperreports.engine.JREmptyDataSource;
import net.sf.jasperreports.engine.JRException;
import net.sf.jasperreports.engine.JasperFillManager;
import net.sf.jasperreports.engine.JasperPrint;
import net.sf.jasperreports.engine.data.JRTableModelDataSource;
import net.sf.jasperreports.swing.JRViewer;
import org.openide.windows.WindowManager;

/**
 *
 * @author Sergey Karavaev
 */
public class ReportGenerator {

    private static ReportGenerator instance = null;

    public static ReportGenerator getInstance() {
        if (null == instance) {
            instance = new ReportGenerator();
        }
        return instance;
    }

    /**
     * Generate Jasper Print.
     *
     * @param parametrs map of params
     * @param reportName name of jasper print
     * @return
     * @throws JRException in case of failures
     */
    public JasperPrint generateReport(Map<String, Object> parametrs, String reportName) throws JRException {

        JasperPrint jasperPrint = JasperFillManager.fillReport(this.getClass()
                .getClassLoader().getResourceAsStream(reportName),
                parametrs, new JREmptyDataSource());
        return jasperPrint;
    }

    /**
     * Show generated report in JDialog.
     *
     * @param jasperPrint
     */
    public void showReport(JasperPrint jasperPrint) {
        JRViewer reportViewer = new JRViewer(jasperPrint);
        JDialog dialog = new JDialog(WindowManager.getDefault().getMainWindow(), true);
        dialog.setTitle("Печать отчета");
        dialog.setPreferredSize(reportViewer.getPreferredSize());
        dialog.getContentPane().add(reportViewer);
        dialog.setSize(1000, 1000);
        dialog.setLocationRelativeTo(null);
        dialog.setVisible(true);
    }

    /**
     * Generates JasperPrint from given table.
     *
     * @param table table to get info from
     * @return
     */
    public JasperPrint generateDynamicReport(JTable table, String title) throws JRException {
        FastReportBuilder drb = new FastReportBuilder();

        // Define all styles used for report
        Style columDetailWhite = new Style();
        columDetailWhite.setOverridesExistingStyle(true);
        Border columnDetailBorder = Border.THIN();
        columnDetailBorder.setColor(Color.BLACK);
        columDetailWhite.setBorder(columnDetailBorder);
        columDetailWhite.setBackgroundColor(Color.WHITE);
        columDetailWhite.setHorizontalAlign(HorizontalAlign.CENTER);
        columDetailWhite.setVerticalAlign(VerticalAlign.TOP);
        columDetailWhite.setStreching(Stretching.RELATIVE_TO_BAND_HEIGHT);
        columDetailWhite.setStretchWithOverflow(true);

        List<String> colNames = new ArrayList<>();
        for (int i = 0; i < table.getColumnCount(); ++i) {
            colNames.add(table.getColumnName(i));
        }

        for (String heading : colNames) {
            String key = heading;
            AbstractColumn column = ColumnBuilder.getNew().setColumnProperty(key, String.class)
                    .setTitle(key).setWidth(table.getColumn(heading).getWidth())
                    .setStyle(columDetailWhite).build();
            drb.addColumn(column);
        }

        drb.setAllowDetailSplit(false);
        drb.setUseFullPageWidth(true);
        drb.setPageSizeAndOrientation(Page.Page_A4_Landscape());

        Style titleStyle = new Style("subtitle_style");
        titleStyle.setFont(new Font(11, Font._FONT_ARIAL, false));
        titleStyle.setHorizontalAlign(HorizontalAlign.RIGHT);
        titleStyle.setStretchWithOverflow(true);
        titleStyle.setStreching(Stretching.NO_STRETCH);

        drb.setTitleStyle(titleStyle)
                .setTitleHeight(new Integer(20));

        drb.setTitle(title);

        DynamicReport dr = drb.build();
        TableModel tm = prepareFilteredTableModel(table);
        JRDataSource ds = new JRTableModelDataSource(tm);
        JasperPrint jasperPrint = DynamicJasperHelper.generateJasperPrint(dr, new ClassicLayoutManager(), ds);
        return jasperPrint;
    }

    /**
     * Prepare new table model to show based on filtered user table.
     *
     * @param table table to get content of.
     * @return new table model with filtered data.
     */
    private TableModel prepareFilteredTableModel(JTable table) {
        String[][] data = new String[table.getRowCount()][table.getColumnCount()];
        for (int i = 0; i < table.getRowCount(); ++i) {
            for (int j = 0; j < table.getColumnCount(); ++j) {
                if (null != table.getValueAt(i, j)) {
                    Object temp = table.getValueAt(i, j);
                    if (temp instanceof Date) {
                        data[i][j] = DateUtils.getDefaultFormattedString((Date) temp);
                    } else {
                        data[i][j] = temp.toString();
                    }
                } else {
                    data[i][j] = "";
                }
            }
        }
        String[] columnName = new String[table.getColumnCount()];
        for (int i = 0; i < table.getColumnCount(); ++i) {
            columnName[i] = table.getColumnName(i);
        }
        DefaultTableModel tm = new DefaultTableModel(data, columnName);
        return tm;
    }

}
